package org.hepeng.workx.spring.cloud.netflix.zuul.route;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.cloud.netflix.zuul.filters.Route;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 *
 * @author he peng
 */

@Slf4j
public class CompositeZuulRoutingRewriteMatch extends AbstractZuulRoutingRewriteMatch {

    private List<Class<? extends AbstractZuulRoutingRewriteMatch>> rewriteMatchClasses = Collections.synchronizedList(new ArrayList<>());
    private List<AbstractZuulRoutingRewriteMatch> rewriteMatches = Collections.synchronizedList(new ArrayList<>());


    public CompositeZuulRoutingRewriteMatch(List<Class<? extends AbstractZuulRoutingRewriteMatch>> rewriteMatcheClasses ,
                                            HttpServletRequest request, String originalUri, List<Route> routes) {
        super(request, originalUri, routes);
        if (CollectionUtils.isNotEmpty(rewriteMatcheClasses)) {
            this.rewriteMatchClasses.addAll(rewriteMatcheClasses);
            Object[] args = {request, originalUri, routes};
            Class clazz = null;
            try {
                for (Class<? extends AbstractZuulRoutingRewriteMatch> rewriteMatchClass : this.rewriteMatchClasses) {
                    clazz = rewriteMatchClass;
                    Constructor<? extends AbstractZuulRoutingRewriteMatch> constructor = rewriteMatchClass.getDeclaredConstructor(HttpServletRequest.class, String.class, List.class);
                    constructor.setAccessible(true);
                    AbstractZuulRoutingRewriteMatch rewriteMatch = constructor.newInstance(args);
                    this.rewriteMatches.add(rewriteMatch);
                }
            } catch (Throwable t) {
                throw new IllegalStateException(clazz.getName() + " class cannot be initialized , constructor args [" + args + "]", t);
            }
        }
    }


    @Override
    protected String getApplicationId() {
        return "";
    }

    @Override
    protected boolean matchRoute(Route route, String appId) {

        for (AbstractZuulRoutingRewriteMatch rewriteMatch : this.rewriteMatches) {
            String applicationId = rewriteMatch.getApplicationId();
            boolean matchRoute = rewriteMatch.matchRoute(route, applicationId);
            if (matchRoute) {
                return true;
            }
        }
        return false;
    }

}
